package twi;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.HashMap;

import jtools.files.TextFile;
import twi.filter.DropAnonFilter;
import twi.query.SparqlQuery;
import twi.result.QueryResult;

import com.hp.hpl.jena.ontology.Individual;
import com.hp.hpl.jena.ontology.OntClass;
import com.hp.hpl.jena.ontology.OntModelSpec;
import com.hp.hpl.jena.ontology.impl.OntModelImpl;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.Property;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.rdf.model.Statement;
import com.hp.hpl.jena.util.iterator.ExtendedIterator;

public class OWLModel extends OntModelImpl {

	public static void main(String[] arg) throws IOException {
		String sparql = " SELECT ?sub ?pre ?obj \n WHERE { ?sub ?pre ?obj. } ";
		OWLModel model = OWLModel.readOWLFile(new File("TWI6.owl"));
		model.add((Statement) null);
		SparqlQuery query = new SparqlQuery(sparql, model);
		QueryResult qrs = QueryManager.executeQuery(query);
		String[] title = qrs.asTable().getTitleRow();
		for (int i = 0; i < title.length; i++)
			System.out.print(title[i] + "  |  ");
		System.out.println();
		String[][] val = qrs.asTable().getValues(true);
		for (int i = 0; i < val.length; i++) {
			for (int j = 0; j < val[i].length; j++)
				System.out.print(val[i][j] + "  |  ");
			System.out.println();
		}
	}

	private String basePrefix = null;
	private File baseFile = null;
	private HashMap<String, String> nameMap = new HashMap<String, String>();
	
	private OWLModel(OntModelSpec spec) {
		super(spec);
		setup();
	}

	private OWLModel(OntModelSpec spec, Model model) {
		super(spec, model);
		setup();
	}

	private void setup(){
		ExtendedIterator iter = this.listIndividuals().filterDrop(new DropAnonFilter());
		while(iter.hasNext()){
			Individual indi = (Individual) iter.next();
			String name = indi.getLocalName();
			nameMap.put(name, name);
		}
		iter = listClasses().filterDrop(new DropAnonFilter());
		while(iter.hasNext()){
			OntClass oc = (OntClass)iter.next();
			String name = oc.getLocalName();
			nameMap.put(name, name);
		}
	}
	public static OWLModel readOWLFile(File file) throws IOException {
		String uri = null;
		TextFile tf = new TextFile();
		tf.readFile(file, false);
		while (tf.hasNext()) {
			String line = tf.getNextLine();
			if (line.contains("xml:base=\"http:")) {
				uri = line.replace(">", "");
				uri = uri.replace("xml:base=", "");
				uri = uri.replace("\"", "");
				uri = uri.replace(" ", "");
				break;
			}else if (line.trim().startsWith("xmlns=\"http://")){
				uri = line.replace("xmlns=\"", "");
				uri = uri.replace("\"", "");
				uri = uri.replace(" ", "");
				break;
			}
				
		}
		tf.closeFile();
		if (uri == null) {
			throw new IOException("Could not find base URI");
		}
		OWLModel ontologyModel = new OWLModel(OntModelSpec.OWL_MEM, null);

		try {
			ontologyModel.getDocumentManager().addAltEntry(uri,
					file.toURI().toURL().toString());
			ontologyModel.read(uri);
			ontologyModel.setBasePrefix(uri);
			ontologyModel.setBaseFile(file);
			ontologyModel.setup();
		} catch (MalformedURLException e) {
			throw new IOException(e);
		}
		return ontologyModel;
	}

	private void setBaseFile(File file) {
		this.baseFile = file;
	}

	public String getBasePrefix() {
		return basePrefix;
	}

	public void setBasePrefix(String basePrefix) {
		if (basePrefix.endsWith("#"))
			this.basePrefix = basePrefix;
		else
			this.basePrefix = basePrefix + "#";
	}

	@Override
	public OntClass getOntClass(String uri) {
		OntClass oc =  super.getOntClass(uri);
		if (oc != null)
			return oc;
		oc = super.getOntClass(getBasePrefix()+uri);
		return oc;
	}

	@Override
	public Individual getIndividual(String uri) {
		Individual in = super.getIndividual(uri);
		if (in != null)
			return in;
		in = super.getIndividual(getBasePrefix()+uri);
		return in;
	}

	@Override
	public Property getProperty(String uri) {
		if (uri == null)
			return null;
		Property p = super.getProperty(uri);
		if (p != null)
			return p;
		p = super.getProperty(getBasePrefix()+uri);
		return p;
	}

	public String createIndividualName(String localName) {
		int c = 0;
		String n = localName;
		while(nameMap.containsKey(n))
			n = localName+c++;
		return n;
	}


	@Override
	public Individual createIndividual(String uri, Resource cls) {
		Individual out = super.createIndividual(uri, cls);
		this.nameMap.put(out.getLocalName(), out.getLocalName());
		return out;
	}

}
